#include <iostream>
#include <memory>
using std::cout;
using std::endl;

// #define mode1
#ifdef mode1 // 简单工厂模式
class Fruit
{
public:
    virtual void name() = 0; // 抽象类
};

class Apple : public Fruit
{
public:
    virtual void name() override
    {
        std::cout << "苹果" << std::endl;
    }
};

class Banana : public Fruit
{
public:
    virtual void name() override
    {
        std::cout << "香蕉" << std::endl;
    }
};

class Orange : public Fruit
{
public:
    virtual void name() override
    {
        std::cout << "橘子" << std::endl;
    }
};

class FruitFactory
{
public:
    static std::shared_ptr<Fruit> CreateInstance(const std::string &name)
    {
        if (name == "苹果")
            return std::make_shared<Apple>();
        else if (name == "香蕉")
            return std::make_shared<Banana>();
        else
            return std::make_shared<Orange>();
    }
};
int main()
{
    cout << "工厂方法模式" << endl;

    std::shared_ptr<Fruit> sf = FruitFactory::CreateInstance("苹果");
    sf->name();

    sf = FruitFactory::CreateInstance("橘子");
    sf->name();

    sf = FruitFactory::CreateInstance("香蕉");
    sf->name();
    return 0;
}

#endif

// #define mode2 // 工厂方法模式
#ifdef mode2

class Fruit
{
public:
    virtual void name() = 0; // 抽象类
};

class Apple : public Fruit
{
public:
    virtual void name() override
    {
        std::cout << "苹果" << std::endl;
    }
};

class Banana : public Fruit
{
public:
    virtual void name() override
    {
        std::cout << "香蕉" << std::endl;
    }
};

class FruitFactory
{
public:
    virtual std::shared_ptr<Fruit> CreateInstance() = 0;
};
class AppleFactory : public FruitFactory
{
public:
    virtual std::shared_ptr<Fruit> CreateInstance() override
    {
        return std::make_shared<Apple>();
    }
};
class BananaFactory : public FruitFactory
{
public:
    virtual std::shared_ptr<Fruit> CreateInstance() override
    {
        return std::make_shared<Banana>();
    }
};
int main()
{
    cout << "工厂方法模式" << endl;
    std::shared_ptr<FruitFactory> sff(new AppleFactory());
    std::shared_ptr<Fruit> sf = sff->CreateInstance();
    sf->name();

    sff.reset(new BananaFactory());
    sf = sff->CreateInstance();
    sf->name();
    return 0;
}
#endif

#define mode3 // 抽象工厂模式
#ifdef mode3
class Fruit
{
public:
    virtual void name() = 0; // 抽象类
};
class Apple : public Fruit
{
public:
    virtual void name() override
    {
        std::cout << "苹果" << std::endl;
    }
};
class Banana : public Fruit
{
public:
    virtual void name() override
    {
        std::cout << "香蕉" << std::endl;
    }
};

class Animal
{
public:
    virtual void name() = 0;
};
class Dog : public Animal
{
public:
    virtual void name() override
    {
        cout << "小狗" << endl;
    }
};
class Sheep : public Animal
{
public:
    virtual void name() override
    {
        cout << "小🐏" << endl;
    }
};

class Factory
{
public:
    virtual std::shared_ptr<Fruit> getFruit(const std::string &name) = 0;
    virtual std::shared_ptr<Animal> getAnimal(const std::string &name) = 0;
};
class FruitFactory : public Factory
{
public:
    virtual std::shared_ptr<Fruit> getFruit(const std::string &name)
    {
        if (name == "苹果")
            return std::make_shared<Apple>();
        else
            return std::make_shared<Banana>();
    }
    virtual std::shared_ptr<Animal> getAnimal(const std::string &name)
    {
        return std::shared_ptr<Animal>(); // 一个空的智能指针
    }
};
class Animalfactory : public Factory
{
public:
    virtual std::shared_ptr<Animal> getAnimal(const std::string &name)
    {
        if (name == "小狗")
            return std::make_shared<Dog>();
        else
            return std::make_shared<Sheep>();
    }
    virtual std::shared_ptr<Fruit> getFruit(const std::string &name)
    {
        return std::shared_ptr<Fruit>(); // 一个空的智能指针
    }
};

class FactoryProducer
{
    public:
        static std::shared_ptr<Factory> createFactory(const std::string& name)
        {
            if(name == "水果") return std::make_shared<FruitFactory>();
            else return std::make_shared<Animalfactory>();
        }
};
int main()
{
    cout << "抽象工厂模式" << endl;
    std::shared_ptr<Factory> sf = FactoryProducer::createFactory("水果");
    std::shared_ptr<Fruit> fruit = sf->getFruit("苹果");
    fruit->name();

    fruit = sf->getFruit("香蕉");
    fruit->name();

    std::shared_ptr<Factory> sfa = FactoryProducer::createFactory("动物");
    std::shared_ptr<Animal> animal = sfa->getAnimal("小狗");
    animal->name();

    animal = sfa->getAnimal("小🐏");
    animal->name();
    return 0;
}
#endif